/***************************************************************************
 *   Copyright (C) 2008 by Jesse Crossen   *
 *   jesse.crossen@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef LISTENER_H
#define LISTENER_H

#include <iostream>

#include "portaudio.h"

#include <QObject>
#include <QComboBox>

// the sample rate and buffer size to listen with
#define SAMPLE_RATE (22050)
#define FRAMES_PER_BUFFER (2048)

/**
	@author Jesse Crossen <jesse.crossen@gmail.com>
*/
class Listener : public QObject
{
Q_OBJECT
public:
  Listener(QObject *parent = 0);
  ~Listener();
  
  // holds info about the system's audio devices
  struct DeviceInfo {
    QString name;
    int index;
  };
  // a list of audio devices
  QList<DeviceInfo> Devices;
  // the currently selected audio device index
  int currentDevice;
  // fill a combobox for selecting audio inputs
  void FillDeviceCombo(QComboBox * combo);
  
  // start listening to audio data
  int Listen();
  void StopListening();

protected:
  // the stream we are currently listening on
  PaStream *stream;
  // a wrapper for portaudio calls that handles errors
  int paCall(PaError err);

public slots:
  void setDevice(int index);

signals:
    void audioHeard(const float *buffer, unsigned long framesPerBuffer,
                    float sampleRate, float peak);

private:

  // the static callback for receiving audio data
  static int paCallback(const void *inputBuffer, void *outputBuffer,
                        unsigned long framesPerBuffer,
                        const PaStreamCallbackTimeInfo* timeInfo,
                        PaStreamCallbackFlags statusFlags,
                        void *userData)
  {
    // prevent unused variable warnings
    (void)outputBuffer;
    (void)timeInfo;
    (void)statusFlags;
    // find the signal peak
    const float * in = (const float *)inputBuffer;
    float s = 0.0;
    float peak = 0.0;
    for(unsigned long i = 0; i < framesPerBuffer; i++) {
      s = *in++;
      if (s > peak) peak = s;
    }
    // proxy to the member callback
    return ((Listener*)userData)->internalCallback(
              (const float *)inputBuffer, framesPerBuffer, SAMPLE_RATE, peak);
  }
  // the internal member callback for audio data
  int internalCallback(const float *buffer, unsigned long framesPerBuffer,
                        float sampleRate, float peak)
  {
    // emit this as a signal
    emit audioHeard(buffer, framesPerBuffer, sampleRate, peak);
    return(0);
  }

};

#endif
